package service

import (
	"errors"
	"github.com/go-admin-team/go-admin-core/sdk/service"
	"github.com/tidwall/gjson"
	"gorm.io/gorm"
	"io/ioutil"
	"net/http"
	"net/url"
	"sort"
	"strconv"
	"strings"
	"time"
	"vrcm/src/vrcm/app/admin/models"
	"vrcm/src/vrcm/app/admin/models/live"
	"vrcm/src/vrcm/app/admin/service/dto/live"
	"vrcm/src/vrcm/common/actions"
	"vrcm/src/vrcm/common/apis"
	cDto "vrcm/src/vrcm/common/dto"
	ext "vrcm/src/vrcm/envconfig"
)

type RecordListView struct {
	service.Service
}

// GetPage 获取RecordListView列表
func (e *RecordListView) GetPage(c *dto.RecordListViewGetPageReq, list *[]live.RecordListView, count *int64) error {
	var err error
	var data live.RecordListView

	err = e.Orm.Model(&data).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).
		Where("is_confirm = 1").
		Order("sort").
		Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("RecordListViewService GetPage error:%s \r\n", err)
		return err
	}
	return nil
}

// GetPageByTime 获取RecordListView列表
func (e *RecordListView) GetPageByTime(c *dto.RecordListViewGetPageReq, model *live.RecordListViewByTime, count *int64) error {
	var err error
	var data live.RecordListView
	yearData := make([]live.RecordListView, 0, 5)
	pastWeek := time.Now().AddDate(0, 0, -7).Unix()
	pastMonth := time.Now().AddDate(0, -1, 0).Unix()
	pastYear := time.Now().AddDate(-1, 0, 0).Unix()
	err = e.Orm.Model(&data).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).
		Where("is_confirm = 1 and file_time >= ?", pastYear).
		Order("sort").
		Find(&yearData).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("RecordListViewService GetPage error:%s \r\n", err)
		return err
	}
	weekData := make([]live.RecordListView, 0, 5)

	err = e.Orm.Model(&data).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).
		Where("is_confirm = 1 and file_time >= ?", pastWeek).
		Order("sort").
		Find(&weekData).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("RecordListViewService GetPage error:%s \r\n", err)
		return err
	}
	monthData := make([]live.RecordListView, 0, 5)
	err = e.Orm.Model(&data).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).
		Where("is_confirm = 1 and file_time >= ?", pastMonth).
		Order("sort").
		Find(&monthData).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("RecordListViewService GetPage error:%s \r\n", err)
		return err
	}

	model.YearData = yearData
	model.YearCount = len(yearData)
	model.MonthData = monthData
	model.MonthCount = len(monthData)
	model.WeekData = weekData
	model.WeekCount = len(weekData)
	return nil
}

func (e *RecordListView) GetPageRecordList(c *dto.RecordListGetPageReq, list *[]live.RecordList, count *int64) error {
	var err error
	var data live.RecordList

	db := e.Orm.Model(&data).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		)
	if c.StartTime > 0 {
		db.Where("file_time>?", c.StartTime)
	}
	if c.EndTime > 0 {
		db.Where("file_time<?", c.EndTime)
	}
	db.Order("file_time desc")
	err = db.Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("RecordListViewService GetPageRecordList error:%s \r\n", err)
		return err
	}

	return nil
}

func (e *RecordListView) GetPageNeedRecordList(c *dto.RecordListGetPageReq, list *[]live.RecordList, count *int64) error {
	var err error
	var data live.RecordList

	db := e.Orm.Model(&data).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		)
	if c.StartTime > 0 {
		db.Where("file_time>?", c.StartTime)
	}
	if c.EndTime > 0 {
		db.Where("file_time<?", c.EndTime)
	}
	db.Order("file_time desc")
	err = db.Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("RecordListViewService GetPageRecordList error:%s \r\n", err)
		return err
	}

	recordViews := make([]live.RecordListView, 0, 5)
	//获取需要展示的录制文件记录
	if c.BasicId > 0 {
		err = e.Orm.Model(&live.RecordListView{}).Where("basic_id = ?", c.BasicId).Find(&recordViews).Error
		if err != nil {
			e.Log.Errorf("RecordListView GetPageNeedRecordList error:%s \r\n", err)
			return err
		}
	}

	//比较录制文件记录和需要展示的录制文件记录 将展示列表里不存在的录制文件记录取出来
	recordMaps := make(map[string]struct{})
	for _, v := range recordViews {
		key := v.TenantId + models.Delimiter + v.RecordId
		_, ok := recordMaps[key]
		if !ok {
			recordMaps[key] = struct{}{}
		}
	}

	for k, v := range *list {
		v := v
		key := v.TenantId + models.Delimiter + v.RecordId

		_, ok := recordMaps[key]
		if ok {
			*(&((*list)[k].IsShow)) = 2
		} else {
			*(&((*list)[k].IsShow)) = 1
		}
	}

	return nil
}

// Get 获取RecordListView对象
func (e *RecordListView) Get(d *dto.RecordListViewGetReq, p *actions.DataPermission, model *live.RecordListView) error {
	var data live.RecordListView

	err := e.Orm.Model(&data).
		Scopes(
			actions.Permission(data.TableName(), p),
		).
		First(model, d.GetId()).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		err = errors.New("查看对象不存在或无权查看")
		e.Log.Errorf("Service GetRecordListView error:%s \r\n", err)
		return err
	}
	if err != nil {
		e.Log.Errorf("db error:%s", err)
		return err
	}
	return nil
}

// GetCount 获取总数
func (e *RecordListView) GetCount(basicId int) (int64, error) {
	var err error
	var count int64
	err = e.Orm.Model(&live.RecordListView{}).Where("basic_id =?", basicId).Count(&count).Error
	if err != nil {
		e.Log.Errorf("RecordListViewService getCount error:%s \r\n", err)
		return 0, err
	}
	return count, nil
}

// Insert 创建RecordListView对象
func (e *RecordListView) Insert(c *dto.RecordListViewMultiInsertReq) error {
	var err error
	data := make([]live.RecordListView, 0, 10)
	c.Generate(&data)
	err = e.Orm.Create(&data).Error
	if err != nil {
		e.Log.Errorf("RecordListViewService Insert error:%s \r\n", err)
		return err
	}
	return nil
}

// Update 修改RecordListView对象
func (e *RecordListView) Update(c *dto.RecordListViewUpdateReq) error {
	var err error
	var data = live.RecordListView{}

	if len(c.LogoUrl) > 0 {
		b := e.IsImageURL(c.LogoUrl)
		if !b {
			return errors.New(string(apis.ImageError.Code))
		}
	}
	e.Orm.First(&data, c.GetId())
	if data.Id <= 0 {
		e.Log.Errorf("RecordListViewService Save error:%s \r\n", "未找到相关记录")
	}

	c.Generate(&data)

	db := e.Orm.Save(&data)
	if err = db.Error; err != nil {
		e.Log.Errorf("RecordListViewService Save error:%s \r\n", err)
		return err
	}
	return nil
}

// Remove 删除RecordListView
func (e *RecordListView) Remove(d *dto.RecordListViewDeleteReq) error {
	var data live.RecordListView

	db := e.Orm.Model(&data).Delete(&data, d.GetId())
	if err := db.Error; err != nil {
		e.Log.Errorf("Service RemoveRecordListView error:%s \r\n", err)
		return err
	}
	if db.RowsAffected == 0 {
		return errors.New("数据不存在")
	}
	return nil
}

// RemoveRecord 删除RecordList
func (e *RecordListView) RemoveRecord(d *dto.RecordListViewDeleteReq) error {
	var data live.RecordList

	db := e.Orm.Model(&data).Delete(&data, d.GetId())
	if err := db.Error; err != nil {
		e.Log.Errorf("RemoveRecordw error:%s \r\n", err)
		return err
	}
	return nil
}

// SyncRecord 创建RecordList对象
func (e *RecordListView) SyncRecord(c *dto.SyncRecordReq) error {

	//根据基本信息id获取直播流信息
	var basic live.LiveBasic
	e.Orm.Model(&live.LiveBasic{}).Where("id = ? and is_delete = 2", c.BasicId).Find(&basic)
	var record live.LiveMonitorRecord
	e.Orm.Model(&live.LiveMonitorRecord{}).Where("tenant_id = ? and basic_id = ? and is_delete = 2", c.TenantId, c.BasicId).Find(&record)
	if record.Id <= 0 {
		return errors.New("未找到直播间信息")
	}
	params := url.Values{}
	urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/live_record/search/recordsByCon"
	Url, err := url.Parse(urlString)
	if err != nil {
		return err
	}

	params.Set("live_id", record.LiveId)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	e.Log.Trace(urlPath)
	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return err
	}
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	response, err := client.Do(request)
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return err
	}
	result := gjson.Parse(string(body))
	if result.Get("code").Int() != http.StatusOK {
		return errors.New(result.Get("message").String())
	}

	//存储录制文件记录
	now := time.Now().Unix()
	records := make([]live.RecordList, 0, 10)
	recordViews := make([]live.RecordListView, 0, 10)
	arr := result.Get("data")

	//单独处理盒子问题
	if c.IsConfirm == 2 {
		arr.ForEach(func(key, value gjson.Result) bool {
			tempRecord := live.RecordList{}
			tempRecord.TenantId = c.TenantId
			tempRecord.BasicId = c.BasicId
			tempRecord.LiveId = value.Get("live_id").String()
			tempRecord.FileId = value.Get("id").String()
			tempRecord.TaskId = value.Get("taskId").String()
			tempRecord.RecordId = value.Get("id").String()
			tempRecord.RecordUrl = value.Get("URL").String()
			tempRecord.FileName = basic.LiveName
			tempRecord.FileType = value.Get("type").String()
			tempRecord.FileTime = value.Get("createTime").Int()
			tempRecord.Duration = value.Get("duration").Int()
			tempRecord.CreateBy = c.CreateBy
			tempRecord.CreateTime = now
			tempRecord.UpdateTime = now
			records = append(records, tempRecord)
			return true // keep iterating
		})
		if len(records) > 0 {
			//先删除录制文件记录
			err = e.Orm.Model(&live.RecordList{}).Where("live_id = ? and tenant_id = ?", record.LiveId, record.TenantId).Delete(&live.RecordList{}).Error
			if err != nil {
				e.Log.Errorf("Service SyncRecordList error:%s \r\n", err)
				return err
			}
			//在插入录制文件记录
			err = e.Orm.Model(&live.RecordList{}).Create(&records).Error
			if err != nil {
				e.Log.Errorf("RecordListService Insert error:%s \r\n", err)
				return err
			}
		}
	} else if c.IsConfirm == 1 {
		count, _ := e.GetCount(basic.Id)
		arr.ForEach(func(key, value gjson.Result) bool {
			if value.Get("taskId").String() == basic.TaskId {
				tempRecord := live.RecordListView{}
				tempRecord.TenantId = c.TenantId
				tempRecord.BasicId = c.BasicId
				tempRecord.LiveId = value.Get("live_id").String()
				//tempRecord.FileId = value.Get("id").String()
				tempRecord.TaskId = value.Get("taskId").String()
				tempRecord.RecordId = value.Get("id").String()
				tempRecord.RecordUrl = value.Get("URL").String()
				tempRecord.FileName = basic.LiveName
				tempRecord.FileType = value.Get("type").String()
				tempRecord.FileTime = value.Get("createTime").Int()
				tempRecord.Duration = value.Get("duration").Int()
				tempRecord.OperatorType = 1
				tempRecord.Sort = int(count) + 1
				tempRecord.CreateBy = c.CreateBy
				tempRecord.CreateTime = now
				tempRecord.UpdateTime = now
				count++
				recordViews = append(recordViews, tempRecord)
			}
			return true // keep iterating
		})
		if len(recordViews) > 0 {
			err = e.Orm.Create(&live.RecordListView{}).Create(&recordViews).Error
			if err != nil {
				e.Log.Errorf("RecordListView Insert error:%s \r\n", err)
				return err
			}
		}
	}

	return nil
}

// GetNeedToAddRecords 获取需要添加录制文件的列表
func (e *RecordListView) GetNeedToAddRecords(c *dto.GetNeedToAddRecordsReq, count *int64) ([]live.RecordListModel, error) {

	var stream live.LiveMonitorRecord
	records := make([]live.RecordList, 0, 10)
	recordViews := make([]live.RecordListView, 0, 10)
	result := make([]live.RecordListModel, 0, 10)
	//获取直播间直播流
	e.Orm.Model(&live.LiveMonitorRecord{}).Where("basic_id =? and tenant_id=? and is_delete =2", c.BasicId, c.TenantId).Find(&stream)
	if stream.Id <= 0 {
		err := errors.New("未找到直播流记录")
		e.Log.Errorf("Service GetNeedToAddRecords error:%s \r\n", err)
		return nil, err
	}

	//分页获取录制文件记录
	//e.Orm.Model(&live.RecordList{}).Where("tenant_id =? and live_id= ?", c.TenantId, stream.LiveId).Find(&records)
	//if len(records) <= 0 {
	//	return nil, nil
	//}
	err := e.Orm.Model(&live.RecordList{}).
		Scopes(
			cDto.MakeCondition(c.GetAddRecordNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).
		Find(&records).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("RecordList GetPage error:%s \r\n", err)
		return nil, err
	}
	//获取需要展示的录制文件记录
	e.Orm.Model(&live.RecordListView{}).Where("tenant_id =? and basic_id = ?", c.TenantId, c.BasicId).Find(&recordViews)

	//比较录制文件记录和需要展示的录制文件记录 将展示列表里不存在的录制文件记录取出来
	recordMaps := make(map[string]struct{})
	for _, v := range recordViews {
		key := strconv.Itoa(v.BasicId) + models.Delimiter + v.TenantId + models.Delimiter + v.RecordId
		_, ok := recordMaps[key]
		if !ok {
			recordMaps[key] = struct{}{}
		}
	}

	for _, v := range records {
		v := v
		key := strconv.Itoa(v.BasicId) + models.Delimiter + v.TenantId + models.Delimiter + v.RecordId
		_, ok := recordMaps[key]
		model := live.RecordListModel{}
		model.Record = v
		model.IsShow = 1
		if ok {
			model.IsShow = 2
		}
		result = append(result, model)
	}

	//按创建时间倒叙
	sort.Slice(result, func(i, j int) bool {
		return result[i].Record.FileTime > result[j].Record.FileTime
	})
	////做分页处理
	//start, end := apis.SlicePage(c.PageIndex, c.PageSize, len(result))
	//*count = len(result[start:end])
	//fmt.Println(start, end)
	return result, nil

}

// RecordUpOrDown 上移下移
func (e *RecordListView) RecordUpOrDown(d *dto.RecordUpOrDownReq) error {
	var data live.RecordListView
	var compareData live.RecordListView
	tx := e.Orm.Begin()

	//获取当前数据
	e.Orm.First(&data, d.Id)
	if data.Id <= 0 {
		return nil
	}
	if d.Type == 1 {
		//获取上一条数据
		e.Orm.Where("sort<? and basic_id=?", data.Sort, data.BasicId).Order("sort desc").Limit(1).Find(&compareData)
	} else {
		//获取下一条数据
		e.Orm.Where("sort>? and basic_id=?", data.Sort, data.BasicId).Order("sort asc").Limit(1).Find(&compareData)
	}
	now := time.Now().Unix()
	data.Sort, compareData.Sort = compareData.Sort, data.Sort
	err := tx.Model(&live.RecordListView{}).Where("id=?", data.Id).Updates(map[string]interface{}{"sort": data.Sort, "update_time": now, "update_by": d.UpdateBy}).Error
	if err != nil {
		e.Log.Errorf("RecordList RecordUpOrDown error:%s \r\n", err)
		tx.Rollback()
		return err
	}
	err = tx.Model(&live.RecordListView{}).Where("id=?", compareData.Id).Updates(map[string]interface{}{"sort": compareData.Sort, "update_time": now, "update_by": d.UpdateBy}).Error
	if err != nil {
		e.Log.Errorf("RecordList RecordUpOrDown error:%s \r\n", err)
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

func (e *RecordListView) IsImageURL(url string) bool {
	// 常见的图片文件扩展名
	imageExtensions := []string{".jpg", ".jpeg", ".png", ".gif", ".psd", ".bmp", ".tga", ".tiff", ".eps", ".svg", ".pdf"}

	// 将地址转换为小写字母，方便比较
	url = strings.ToLower(url)

	// 去掉链接中的 ? 及其后面的内容
	urlParts := strings.Split(url, "?")
	urlPart := urlParts[0]

	// 检查地址是否以图片文件扩展名结尾
	for _, ext := range imageExtensions {
		if strings.HasSuffix(urlPart, ext) {
			return true
		}
	}

	return false
}
